﻿
using System;
using System.Diagnostics.Contracts;
using System.Linq;
using Adalbertus.BudgetPlanner.Domain;
using Adalbertus.BudgetPlanner.Services.Dto;

namespace Adalbertus.BudgetPlanner.Services.Extensions
{
    public static class DtoConvertExtensions
    {
        public static IDto ToDto(this IEntity entity)
        {
            Contract.Requires<ArgumentNullException>(entity != null);
            Contract.Ensures(Contract.Result<IDto>() != null);

            switch (entity.GetType().Name)
            {
                case "ExternalSource":
                    return ((ExternalSource)entity).ToDto();
                case "CashFlowType":
                    return ((CashFlowType)entity).ToDto();
                case "Budget":
                    return ((Budget)entity).ToDto();
                case "ExpenseItem":
                    return ((ExpenseItem)entity).ToDto();
                case "BudgetPlanItem":
                    return ((BudgetPlanItem)entity).ToDto();
                case "Revenue":
                    return ((Revenue)entity).ToDto();
                default:
                    throw new InvalidOperationException(
                        string.Format("Nie można odnaleźć konwertera z encji do dto dla encji {0}",
                                      entity.GetType().Name));
            }
        }

        public static IDto ToDto(this ExternalSource externalSource)
        {
            Contract.Requires<ArgumentNullException>(externalSource != null);
            Contract.Ensures(Contract.Result<IDto>() != null);
            ExternalSourceDto dto = new ExternalSourceDto
            {
                Id = externalSource.Id,
                IsUnlimited = externalSource.IsUnlimited,
                Name = externalSource.Name
            };
            dto.Items =
                externalSource.Items.Select(i => new ExternalSourceItemDto
                {
                    Id = i.Id,
                    Date = i.Date,
                    Description = i.Description,
                    IsFrozen = i.IsFrozen,
                    Value = i.Value
                }).ToList();
            return dto;
        }

        public static IDto ToDto(this CashFlowType cashFlowType)
        {
            Contract.Requires<ArgumentNullException>(cashFlowType != null);
            Contract.Ensures(Contract.Result<IDto>() != null);

            CashFlowTypeDto dto = new CashFlowTypeDto
            {
                Id = cashFlowType.Id,
                Name = cashFlowType.Name,
                Description = cashFlowType.Description,
            };

            if (cashFlowType.ExternalSource != null)
            {
                dto.ExternalSource = cashFlowType.ExternalSource.ToDto() as ExternalSourceDto;
            }
            return dto;
        }

        public static IDto ToDto(this Budget budget)
        {
            Contract.Requires<ArgumentNullException>(budget != null);
            Contract.Ensures(Contract.Result<IDto>() != null);

            BudgetDto dto = new BudgetDto
            {
                Id = budget.Id,
                DateFrom = budget.DateFrom,
                DateTo = budget.DateTo,
            };
            dto.Expenses = budget.Expenses.Select(e => e.ToDto() as ExpenseItemDto).ToList();
            dto.PlanItems = budget.PlanItems.Select(p => p.ToDto() as BudgetPlanDto).ToList();
            dto.Revenues = budget.Revenues.Select(r => r.ToDto() as RevenueDto).ToList();

            return dto;
        }

        public static IDto ToDto(this ExpenseItem expenseItem)
        {
            Contract.Requires<ArgumentNullException>(expenseItem != null);
            Contract.Ensures(Contract.Result<IDto>() != null);

            ExpenseItemDto dto = new ExpenseItemDto
            {
                Id = expenseItem.Id,
                Date = expenseItem.Date,
                Description = expenseItem.Description,
                FlowType = (CashFlowTypeDto) expenseItem.FlowType.ToDto(),
                Value = expenseItem.Value
            };

            return dto;
        }

        public static IDto ToDto(this BudgetPlan budgetPlan)
        {
            Contract.Requires<ArgumentNullException>(budgetPlan != null);
            Contract.Ensures(Contract.Result<IDto>() != null);

            BudgetPlanDto dto = new BudgetPlanDto
                                    {
                                        Id = budgetPlan.Id,
                                        FlowType = budgetPlan.FlowType.ToDto() as CashFlowTypeDto,
                                    };
            dto.Details = budgetPlan.Details.Select(bp => bp.ToDto() as BudgetPlanItemDto).ToList();
            return dto;
        }

        public static IDto ToDto(this BudgetPlanItem budgetPlanItem)
        {
            Contract.Requires<ArgumentNullException>(budgetPlanItem != null);
            Contract.Ensures(Contract.Result<IDto>() != null);

            BudgetPlanItemDto dto = new BudgetPlanItemDto
                                        {
                                            Id = budgetPlanItem.Id,
                                            Description = budgetPlanItem.Description,
                                            Value = budgetPlanItem.Value
                                        };
            return dto;
        }

        public static IDto ToDto(this Revenue revenue)
        {
            Contract.Requires<ArgumentNullException>(revenue != null);
            Contract.Ensures(Contract.Result<IDto>() != null);

            RevenueDto dto = new RevenueDto
                                 {
                                     Id = revenue.Id,
                                     Date = revenue.Date,
                                     Source = (ExternalSourceDto) revenue.Source.ToDto(),
                                     Value = revenue.Value
                                 };
            return dto;
        }

    }
}
